from xml.sax import make_parser
from xml.sax.handler import ContentHandler

import util

def parse(pbfi_model_filename):
    parser = make_parser()   
    pbfi_descrition_handler = PBFIXmlHandler()
    parser.setContentHandler(pbfi_descrition_handler)
    pbfi_model_fp = open(pbfi_model_filename, 'r') 
    parser.parse(pbfi_model_fp)
    return pbfi_descrition_handler.sections

class PBFIXmlHandler(ContentHandler):
    def __init__(self):
        self.sections = []
        self.array_stack = util.Stack()
        self.in_file = False

    def startElement(self, name, attrs):
        if name == 'file':
            self.in_file = True
        elif self.in_file:
            var_id = attrs.get('id', None)
            var_name = attrs.get('name', None)
            reader = None 
            display = None

            if name == 'int' or name == 'i32':
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'int'
                        }
                display = 'dec'
            elif name == 'i16':
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'int16'
                        }
                display = 'dec'
            elif name == 'i64':
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'int64'
                        }
                display = 'dec'
            elif name == 'string':
                size = attrs.get('size', None)
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'string',
                        'size':size
                        }
                display = 'string'
            elif name == 'byte':
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'byte'
                        }
                display = 'byte'
            elif name == 'float' or name == 'f32':
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'float'
                        }
                display = 'float'
            elif name == 'f64':
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'float64'
                        }
                display = 'float'
            elif name == 'array':
                variable_count_id = attrs.get('count', None)
                reader = {
                        'name':var_name,
                        'id':var_id,
                        'format':'array',
                        'count':variable_count_id,
                        'entries':[]
                        }
                display = 'array'

            if reader != None and display != None:
                self.array_stack.push((reader, display))

        return

    def endElement(self, name):
        if name == 'file':
            self.in_file = False
        else:
            obj = self.array_stack.pop()
            if self.array_stack.is_empty():
                self.sections.append(obj)    
            else:
                self.array_stack.top()[0]['entries'].append(obj)

